from django.db import transaction
from rest_framework import serializers
from celery_tasks.detail.tasks import get_detail_html
from apps.goods.models import SKU, GoodsCategory, SPUSpecification, SpecificationOption, SKUSpecification

class SKUSpecificationSerializer(serializers.ModelSerializer):
    '''
        sku具体规格表序列化器
    '''
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()
    class Meta:
        model = SKUSpecification
        fields = ('spec_id', 'option_id')


class SKUGoodsSerializer(serializers.ModelSerializer):
    '''
        sku序列化器
    '''
    # 指定分类信息
    category_id = serializers.IntegerField()
    # 关联嵌套返回
    category = serializers.StringRelatedField(read_only=True)
    # 指定所关联的spu表信息
    spu_id = serializers.IntegerField()
    # 关联嵌套返回
    spu = serializers.StringRelatedField(read_only=True)
    # 关联的sku具体规格表
    specs = SKUSpecificationSerializer(many=True) #, read_only=True)

    class Meta:
        model = SKU
        fields = '__all__'

    # 重写父类create方法完成sku规格详情保存
    def create(self, validated_data):
        # 开启事务
        with transaction.atomic():
            # 1. 设置保存点
            save_point = transaction.savepoint()
            try:
                # 2. 数据库操作
                # 3. 保存sku表数据
                # 因为sku表中没有specs字段，所以在保存的时候需要删除validated_data中specs数据
                specs = validated_data['specs']
                del validated_data['specs']
                sku = SKU.objects.create(**validated_data)
                # 4. 保存sku具体规格表信息
                # 获取规格信息
                # request = self.context['request']
                # specs = request.data['specs']
                for spec in specs:
                    SKUSpecification.objects.create(sku=sku,
                                                    spec_id=spec['spec_id'],
                                                    option_id=spec['option_id'])
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('保存失败')
            transaction.savepoint_commit(save_point)
            # 执行异步任务生成新的静态页面
            get_detail_html.delay(sku.id)
            return sku

    # 重写update方法
    def update(self, instance, validated_data):
        # 开启事务
        with transaction.atomic():
            # 1. 设置保存点
            save_point = transaction.savepoint()
            try:
                # 2. 数据库操作
                # 3. 修改sku表数据
                # 因为sku表中没有specs字段，所以在保存的时候需要删除validated_data中specs数据
                specs = validated_data['specs']
                del validated_data['specs']
                SKU.objects.filter(id=instance.id).update(**validated_data)
                # 4. 修改sku具体规格表信息
                for spec in specs:
                    SKUSpecification.objects.filter(sku=instance,
                                                    spec_id=spec['spec_id']
                                                    ).update(option_id=spec['option_id'])
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('保存失败')
            transaction.savepoint_commit(save_point)
            sku = SKU.objects.get(id=instance.id)
            # 执行异步任务生成新的静态页面
            get_detail_html.delay(sku.id)
            return sku


class SKUGoodsCategorySerializer(serializers.ModelSerializer):
    '''
        商品分类序列化器
    '''

    class Meta:
        model = GoodsCategory
        fields = ('id', 'name')


class SPUOptineSerializer(serializers.ModelSerializer):
    '''
        商品规格序选项列化器
    '''

    class Meta:
        model = SpecificationOption
        fields = ('id', 'value')


class SPUSpecificationSerializer(serializers.ModelSerializer):
    '''
        商品规格序列化器
    '''
    # 关联序列化返回SPU表数据
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()
    # 关联序列化返回 规格选项信息
    options = SPUOptineSerializer(many=True)  # 使用规格选项序列化器

    class Meta:
        model = SPUSpecification
        fields = '__all__'

